/*
 * Arrow.cpp
 *
 *  Created on: 21/04/2013
 *      Author: gonzalo
 */

#include "Arrow.h"

Arrow::Arrow(GLuint  program, GLfloat radio, GLfloat longitud_arista, bool llena) :
		Figure(program), cara_opaca(llena), finita(false) {

	GLfloat phi;
	GLfloat cosPhi;
	GLfloat sinPhi;

	if (longitud_arista > 1) {
		longitud_arista = 1;
	}

	int segments = 20;
	vertex_buffer_size = 2 + segments;
	vertex_buffer = new GLfloat[3 * vertex_buffer_size];

	set_coords3(vertex_buffer, 0, 0.0, 0.0, 0.0);
	set_coords3(vertex_buffer, 1, 0.0, 0.0, 1.0);

	for (int i = 0; i < segments; i++) {
		phi = 2 * PI * i / segments;
		cosPhi = cos(phi);
		sinPhi = sin(phi);
		set_coords3(vertex_buffer, i + 2, cosPhi * radio, sinPhi * radio, 1.0 - longitud_arista);
	}

	if (llena) { // Para usar con GL_TRIANGLE_FAN
		index_buffer_size = 1 + segments + 1;
		index_buffer = new GLuint[index_buffer_size];
		index_buffer[0] = 1;
		for (int i = 0; i < segments; i++) {
			index_buffer[i + 1] = i + 2;
		}
		index_buffer[segments + 1] = 2;
	} else {

	}
}

Arrow::Arrow(GLuint  program, GLfloat longitud_extremos, GLfloat longitud_arista) :
		Figure(program), cara_opaca(false), finita(true) {

	if (longitud_arista > 1) {
		longitud_arista = 1;
	}

	vertex_buffer_size = 4;
	vertex_buffer = new GLfloat[3 * vertex_buffer_size];

	set_coords3(vertex_buffer, 0, 0.0, 0.0, 0.0);
	set_coords3(vertex_buffer, 1, 0.0, 0.0, 1.0);
	set_coords3(vertex_buffer, 2, 0.0, longitud_extremos / 2, 1.0 - longitud_arista);
	set_coords3(vertex_buffer, 3, 0.0, -longitud_extremos / 2, 1.0 - longitud_arista);
	index_buffer_size = 6;
	index_buffer = new GLuint[index_buffer_size];
	index_buffer[0] = 0;
	index_buffer[1] = 1;
	index_buffer[2] = 1;
	index_buffer[3] = 2;
	index_buffer[4] = 1;
	index_buffer[5] = 3;
}

Arrow::~Arrow() {

}

void Arrow::draw(GLuint program, glm::mat4 & world_matrix) {

	glm::vec3 diffuse_reflectivity = glm::vec3(10.0, 10.0, 10.0);

	GLuint location_diffuse_reflectivity = glGetUniformLocation(program, "Kd");
	if (location_diffuse_reflectivity >= 0) {
		glUniform3fv(location_diffuse_reflectivity, 1, &diffuse_reflectivity[0]);
	}

	glm::mat4 matriz = world_matrix * this->model_matrix;
	GLuint linea[2];

// Normal Matrix
	glm::mat3 normal_matrix = glm::mat3(1.0f);
	if (this->view_matrix != NULL) {
		glm::mat4 aux = (*this->view_matrix) * world_matrix;
		for (int i = 0; i < 3; i++)
			for (int j = 0; j < 3; j++)
				normal_matrix[i][j] = aux[i][j];
	}

// Bind Model Matrix
	GLuint location_world_matrix = glGetUniformLocation(program, "ModelMatrix");
	if (location_world_matrix >= 0) {
		glUniformMatrix4fv(location_world_matrix, 1, GL_FALSE, &matriz[0][0]);
	}

	glEnableClientState(GL_VERTEX_ARRAY);

	glVertexPointer(3, GL_FLOAT, 0, vertex_buffer);

	if (finita) {
		glDrawElements(GL_LINES, index_buffer_size, GL_UNSIGNED_INT, index_buffer);
	} else if (cara_opaca) {
		linea[0] = 0;
		linea[1] = 1;
		glDrawElements(GL_LINES, 2, GL_UNSIGNED_INT, linea);
		glDrawElements(GL_TRIANGLE_FAN, index_buffer_size, GL_UNSIGNED_INT, index_buffer);
	} else {

	}

	//glDrawElements(GL_QUADS, index_buffer_size, GL_UNSIGNED_INT, index_buffer);

	glDisableClientState(GL_VERTEX_ARRAY);
}
